home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Telnet 2.6.1d1 4⁄26⁄94 Folder / Krb / kerberos.c < prev    next >
Text File  |  1994-02-20  |  8KB  |  328 lines

  1. /*
  2.  * kerberos.c
  3.  */
  4.  
  5. #ifdef MPW
  6. #pragma segment 22
  7. #endif
  8.  
  9. #define NCSA_ENC
  10.  
  11. #ifdef TN3270
  12. #pragma segment 3270tcp
  13. #if !defined(USEDUMP)
  14. #include "maclib.h"
  15. #include "termdef.h"
  16. #include "tn3270funcs.h"
  17. #include "globals.h"
  18. #else
  19. #pragma load "tn3270DumpFile"
  20. #endif
  21. #include "telnet.h"
  22. #include "hostform.h"
  23. #endif /* TN3270 */
  24.  
  25. #ifdef NCSA_ENC
  26. #include <String.h>
  27. #include "TelnetHeader.h"
  28. #include "wind.h"
  29. #include "parse.proto.h"
  30. #endif
  31.  
  32. #define TELCMDS 1
  33. #define TELOPTS 1
  34.  
  35. #include "encrypt.proto.h"
  36. #include "kerberos.proto.h"
  37. #include "desproto.h"
  38.  
  39. static short kdriver = 0;        /* .Kerberos driver ref */
  40.  
  41. /*
  42.  * krb_telnet
  43.  * Send Kerberos credentials as a telnet suboption.
  44.  * Return error number if error;
  45.  *
  46.  * Called with doit==false to verify that we have
  47.  * enough credentials.
  48.  */
  49. long krb_telnet (WDATA *cr, char *tp, long doit)
  50. {
  51.     #pragma unused (doit)
  52.     long i, len;
  53.     short s;
  54.     unsigned char *cp, *cn, cannon[256];
  55.     ParamBlockRec pbr, *pb = &pbr;
  56.     krbHiParmBlock khpb, *khipb = &khpb;
  57.     krbParmBlock klpb, *klopb = &klpb;
  58.     unsigned char buf[1258+20];
  59.     Session_Key skey;
  60.     Str255 scratch1, scratch2, kname;
  61.     unsigned char *kp;
  62.     des_cblock sessionKey;
  63.  
  64.     /*
  65.      * Open the .Kerberos driver if not already open
  66.      */
  67.     if (!kdriver) {
  68.         if (s = OpenDriver("\p.Kerberos", &kdriver)) {
  69.             return -1;
  70.         }
  71.     }
  72.     
  73.     /*
  74.      * Figure out the cannonical hosthame.
  75.      * If we used domain lookup, it should be in mp->cannon.
  76.      * Otherwise, we use mp->hname.
  77.      */
  78.     cp = 0;
  79.     cp = (unsigned char *)getcname(cr);
  80.     if (!cp)
  81.         return -1;
  82.  
  83.     /*
  84.      * Get the realm of the host
  85.      */
  86.     strcpy((char *)scratch2, (char *)cp);
  87.     if (scratch2[strlen((char *)scratch2)-1] == '.')
  88.         scratch2[strlen((char *)scratch2)-1] = '\0';
  89.     xbzero(klopb, sizeof(*klopb));
  90.     klopb->host = (char *)scratch2;
  91.     klopb->uRealm = (char *)scratch1;
  92.     if (s = lowcall(cKrbGetRealm, klopb, kdriver))
  93.         return -1;
  94.  
  95.     /* 
  96.      * build rcmd.hostname@realm
  97.      */
  98.     strcpy((char *)cannon, "rcmd.");
  99.     cn = &cannon[5];
  100.     strncpy((char *)cn, (char *)cp, sizeof(cannon)-5);
  101.     cannon[sizeof(cannon)-1] = '\0';
  102.     if (cp = (unsigned char *)strchr((char *)cn, '.'))
  103.         *cp = '\0';
  104.     strcat((char *)cannon, "@");
  105.     strcat((char *)cannon, (char *)scratch1);
  106.     
  107.     /* 
  108.      * use cKrbGetAuthForService to get auth data for telnet option 
  109.      *
  110.      * Similiar to cKrbGetTicketForService except it builds a kerberos "SendAuth" style
  111.        request (with SendAuth and application version numbers preceeding the actual ticket)
  112.           -> service                Formal Kerberos name of service
  113.           -> buf                    Buffer to receive ticket
  114.           -> checksum                checksum for this service
  115.           <-> buflen                    length of ticket buffer (must be at least 1258 bytes)
  116.          <-  sessionKey                for internal use
  117.          <-  schedule                for internal use
  118.      */
  119.  
  120.     xbzero(khipb, sizeof(krbHiParmBlock));
  121.     khipb->service = (char *)cannon;
  122.     khipb->buf = (char *)buf;                /* where to build it */
  123.     khipb->checksum = 0;
  124.     khipb->buflen = sizeof(buf);
  125.     if (s = hicall(cKrbGetTicketForService, khipb, kdriver))
  126.         return s;
  127.     xbcopy(khipb->sessionKey, sessionKey, sizeof(sessionKey));    /* save the session key */
  128.     /*
  129.      * cKrbGetTicketForService put a longword buffer length into the buffer
  130.      * which we don't want, so we ignore it.
  131.      * Make room for first 3 bytes which preceed the auth data.
  132.      */
  133.     cp = &buf[4-3];                        /* skip long, make room for 3 bytes */
  134.     cp[0] = tp[0];                        /* copy type and modifier */
  135.     cp[1] = tp[1];
  136.     cp[2] = KRB_AUTH;                    /* suboption command */
  137.     len = khipb->buflen - sizeof(long) + 3; /* data - 4 + 3 */
  138.  
  139.     xbzero(khipb, sizeof(krbHiParmBlock));    /* get kerberos user name */
  140.     khipb->user = (char *)kname;
  141.     if (s = hicall(cKrbGetUserName, khipb, kdriver))
  142.         return s;
  143.     if (kp = (unsigned char *)strchr((char *)kname, '@'))
  144.         *kp = '\0';
  145.         
  146.     tn_sendsub(cr, OPT_AUTHENTICATION, TNQ_NAME, (char *)kname, strlen((char *)kname));
  147.     tn_sendsub(cr, OPT_AUTHENTICATION, TNQ_IS, (char *)cp, len);
  148.  
  149.     /*
  150.      * If we are going to do mutual authentication, go ahead and 
  151.      * generate the challenge and response here so we won't have to figure
  152.      * out the credentials again later. 
  153.      */
  154.     if (tp[1] & AUTH_HOW_MUTUAL) {
  155.         unsigned char challenge[8];
  156.         des_key_schedule sched;
  157.  
  158.         des_init_random_number_generator(sessionKey);
  159.  
  160.         des_key_sched(sessionKey, sched);
  161.         des_set_random_generator_seed((des_cblock *)sessionKey);
  162.         des_new_random_key(challenge);
  163.         des_ecb_encrypt((unsigned long *)challenge, (unsigned long *)cr->auth_challenge, sched, 1);
  164.         skey.type = SK_DES;                        /* save key for ENCRYPT */
  165.         skey.length = 8;
  166.         skey.data = (unsigned char *)cr->auth_challenge;
  167.         encrypt_session_key(cr->edata, &skey, 0);
  168.         /*
  169.          * Increment the challenge by 1, and encrypt it for
  170.          * later comparison.
  171.          */
  172.         for (i = 7; i >= 0; --i) {
  173.             register long x;
  174.  
  175.             x = (unsigned long)challenge[i] + 1;
  176.             challenge[i] = x;            /* ignore overflow */
  177.             if (x < 256)                /* if no overflow, all done */
  178.                 break;
  179.         }
  180.         des_ecb_encrypt((unsigned long *)challenge, (unsigned long *)cr->auth_response, sched, 1);
  181.         skey.type = SK_DES;                        /* save key for ENCRYPT */
  182.         skey.length = 8;
  183.         skey.data = (unsigned char *)cr->auth_response;
  184.         encrypt_session_key(cr->edata, &skey, 1);
  185.     }
  186.  
  187.     return 0;
  188. }
  189.  
  190.  
  191. /*
  192.  * tn_kerberos_reply
  193.  * Process a AUTHENTICATION REPLY of type KRBEROS_V4.
  194.  */
  195. void tn_kerberos_reply (WDATA *tw, unsigned char *subbuffer)
  196. {
  197.     switch (subbuffer[SB_DATATYPE] & 0xff) {
  198.     case KRB_AUTH:
  199.         break;
  200.     case KRB_REJECT:
  201.         break;
  202.     case KRB_ACCEPT:
  203.         /*
  204.          * If mutual authentication, it is time to send the challenge.
  205.          */
  206.         if (subbuffer[SB_MODIFIER] & AUTH_HOW_MUTUAL)
  207.             tn_send_challenge(tw, subbuffer);
  208.         break;
  209.     case KRB_CHALLENGE:
  210.         break;
  211.     case KRB_RESPONSE:
  212.         /*
  213.          * We got a response to an authorization challenge. Make
  214.          * sure it is the correct response.
  215.          */
  216. #ifdef notdef /* ... ??? */
  217.         if (xbcmp(&subbuffer[SB_DATA], tw->auth_response, 8))
  218.             /*
  219.              * ??? What do we do here? -- presumably clear the connection.
  220.              */
  221.             printf("\n[Challenge failed]\n");
  222.         else
  223.             printf("\n[Challenge succeeded]\n");
  224. #endif
  225.         break;
  226.     }
  227. }
  228.  
  229.  
  230. /*
  231.  * tn_send_challenge
  232.  * Send a challenge
  233.  */
  234. void tn_send_challenge (WDATA *tw, unsigned char *subbuffer)
  235. {
  236.     char buf[2+1+8];
  237.  
  238.     buf[0] = subbuffer[SB_TYPE];
  239.     buf[1] = subbuffer[SB_MODIFIER];
  240.     buf[2] = KRB_CHALLENGE;
  241.     xbcopy(tw->auth_challenge, &buf[3], 8);
  242.  
  243.     tn_sendsub(tw, OPT_AUTHENTICATION, TNQ_IS, buf, sizeof(buf));
  244. }
  245.  
  246.  
  247. short lowcall (long cscode, krbParmBlock *klopb, short kdriver)
  248. {
  249.     short s;
  250.     ParamBlockRec pb;
  251.     
  252.     xbzero(&pb, sizeof(ParamBlockRec));
  253.     *(long *)pb.cntrlParam.csParam = (long)klopb;
  254.     pb.cntrlParam.ioCompletion = nil;
  255.     pb.cntrlParam.ioCRefNum = kdriver;
  256.  
  257.     pb.cntrlParam.csCode = cscode;
  258.     if (s = PBControl(&pb, false))
  259.         return s;
  260.     if (s = pb.cntrlParam.ioResult)
  261.         return s;
  262.     return 0;
  263. }
  264.  
  265.  
  266. short hicall (long cscode, krbHiParmBlock *khipb, short kdriver)
  267. {
  268.     short s;
  269.     ParamBlockRec pb;
  270.     
  271.     xbzero(&pb, sizeof(ParamBlockRec));
  272.     *(long *)pb.cntrlParam.csParam = (long)khipb;
  273.     pb.cntrlParam.ioCompletion = nil;
  274.     pb.cntrlParam.ioCRefNum = kdriver;
  275.  
  276.     pb.cntrlParam.csCode = cscode;
  277.     if (s = PBControl(&pb, false))
  278.         return s;
  279.     if (s = pb.cntrlParam.ioResult)
  280.         return s;
  281.     return 0;
  282. }
  283.  
  284.  
  285. /*
  286.  * bcopy
  287.  * Block copy
  288.  */
  289. void xbcopy (void *src, void *dst, long n)
  290. {
  291.     long i;
  292.     register unsigned char *s = src;
  293.     register unsigned char *d = dst;
  294.  
  295.     for (i = 0; i < n; i++)
  296.         *d++ = *s++;
  297. }
  298.  
  299.  
  300. /*
  301.  * bcmp
  302.  * return 0 if blocks compare ok
  303.  */
  304. long xbcmp (void *src, void *dst, long n)
  305. {
  306.     register char *s = src;
  307.     register char *d = dst;
  308.     
  309.     while (n-- > 0)
  310.         if (*s++ != *d++)
  311.             return 1;
  312.             
  313.     return 0;
  314. }
  315.  
  316.  
  317. /*
  318.  * bzero
  319.  * Block zero
  320.  */
  321. void xbzero (void *dst, long n)
  322. {
  323.     register char *d = dst;
  324.  
  325.     while (n--)
  326.         *d++ = 0;
  327. }
  328.